﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Reflection.Core;
using Pixysoft.Framework.Verifications;
using System.Reflection;
using System.Collections;

namespace Pixysoft.Framework.Reflection
{
    public abstract class DynamicTransparentProxyBase
    {
        private DynamicProxy proxy;

        public DynamicTransparentProxyBase()
        {
        }

        internal void Initialize(DynamicProxy proxy)
        {
            this.proxy = proxy;
        }

        /// <summary>        
        /// </summary>
        /// <param name="target">emit的接口实现类</param>
        /// <param name="name">方法名</param>
        /// <param name="types">方法参数的类型</param>
        /// <param name="paras">方法传入的参数</param>
        /// <returns></returns>
        [CreateMethodCallMessage]
        protected IDynamicMethodCallMessage CreateMethodCallMessage(object target, string name, Type[] types, object[] paras)
        {
            //使用verification 和使用 简单判断：82ms -> 56ms 

            if (target == null || string.IsNullOrEmpty(name) || types == null)
                throw Exceptions.VerificationFailedException(target, name, types);

            MethodInfo methodInfo = target.GetType().GetMethod(name, types);

            if (methodInfo == null)
                throw Exceptions.UnexpectedResultException("get method from target fail, target:" +
                    target + ", method:" + name);

            IDynamicMethodCallMessage message = new DynamicMethodCallMessage(methodInfo, paras);

            return message;
        }

        private object[] RegularParameters(object[] paras)
        {
            if (paras.Length != 1)
                return paras;

            if (paras[0] == null)
                return paras;

            if (!paras[0].GetType().IsArray)
                return paras;

            List<object> list = new List<object>();

            foreach (object para in paras[0] as IList)
            {
                list.Add(para);
            }

            return list.ToArray();
        }

        [TryThrowException]
        protected void TryThrowException(IDynamicMethodReturnMessage message)
        {
            if (message.Exception == null)
                return;

            Exception ex = message.Exception;

            message.Dispose();

            throw ex;
        }

        [TryInvokeProxy]
        protected IDynamicMethodReturnMessage TryInvokeProxy(IDynamicMethodCallMessage inmessage)
        {
            IDynamicMethodReturnMessage outmessage = proxy.Invoke(inmessage);

            inmessage.Dispose();

            return outmessage;
        }

        [TryReturnMethod]
        protected object TryReturnMethod(IDynamicMethodReturnMessage message)
        {
            if (message == null)
                throw new Exception(string.Format("get null return message. object:{0}, method:{1}",
                    message.MethodInfo.DeclaringType.Name,
                    message.MethodInfo.Name));

            object returnValue = message.ReturnValue;

            message.Dispose();

            return returnValue;

            //2010-08-27 把返回结果转型交给代理， 89ms ->74ms

            //object returnValue = Pixysoft.Tools.ParserHelper.Parse(message.MethodInfo.ReturnType, message.ReturnValue, null);

            ////检查返回类型是否一致

            //message.Dispose();

            //return returnValue;
        }

        public DynamicProxy GetProxy()
        {
            return proxy;
        }

        public void Dispose()
        {
            this.proxy = null;
        }


        public class CreateMethodCallMessageAttribute : Attribute { }
        public class TryThrowExceptionAttribute : Attribute { }
        public class TryInvokeProxyAttribute : Attribute { }
        public class TryReturnMethodAttribute : Attribute { }
    }
}
